// Fill out your copyright notice in the Description page of Project Settings.


#include "WGIUserWidget.h"
#include "Group/WidgetGroupLibrary.h"
#include "Nav/WGINavItem.h"
#include "Nav/WGINavInterface.h"
#include "OverrideWidget/WGIButton.h"
#include "OverrideWidget/WGIInputKeySelector.h"
#include "Components/PanelWidget.h"
#include "Components/EditableTextBox.h"
#include "Components/Button.h"
#include "Components/CheckBox.h"
#include "Components/Slider.h"
#include "Components/ComboBox.h"
#include "Components/InputKeySelector.h"
#include "Components/ScrollBox.h"
#include "Components/HorizontalBox.h"
#include "Components/VerticalBox.h"
#include "Components/GridPanel.h"
#include "Components/UniformGridPanel.h"
#include "Components/GridSlot.h"


DEFINE_LOG_CATEGORY(WGI_UserWidgetLog);


UWGI_UserWidget::UWGI_UserWidget(const FObjectInitializer& ObjectInitializer)
	:Super(ObjectInitializer)
{
	//bForceLockOnWidgetFocus = true;
	bOverrideAllChildSetting = true;
	ChildWGIUserWidget.Empty();
	NavDatas.Empty();
	CutomKeyEvents.Empty();
	NavDataCache = nullptr;
	EnterKeyNav = nullptr;
}


void UWGI_UserWidget::BeginDestroy()
{
#if WITH_EDITOR
	WidgetGroupLibrary::GameIsEnd(this);
#endif

	Super::BeginDestroy();
}

void UWGI_UserWidget::AddWidgetToViewport(bool bRemoveLast /*= false*/)
{
	WidgetGroupLibrary::AddWidgetToGroup(this, bRemoveLast);
}

void UWGI_UserWidget::RemoveWidgetFromViewport(bool bRemoveAll /*= false*/)
{
	WidgetGroupLibrary::RemoveWidgetFromGroup(this, bRemoveAll);
}

void UWGI_UserWidget::OnReloadConfigEvent()
{
	for (size_t i = 0; i < NavDatas.Num(); i++)
	{
		FNavDirectionData* Data = NavDatas[i]->GetNavDirectionData();
		if (Data->DownKeyName != NAME_None)
			InputConfigureLibrary::GetOtherInputKeysFromKeyName(Data->DownKeyName, Data->DownDirectionKeys);
		if (Data->UpKeyName != NAME_None)
			InputConfigureLibrary::GetOtherInputKeysFromKeyName(Data->UpKeyName, Data->UpDirectionKeys);
		if (Data->LeftKeyName != NAME_None)
			InputConfigureLibrary::GetOtherInputKeysFromKeyName(Data->LeftKeyName, Data->LeftDirectionKeys);
		if (Data->RightKeyName != NAME_None)
			InputConfigureLibrary::GetOtherInputKeysFromKeyName(Data->RightKeyName, Data->RightDirectionKeys);
	}

	TArray<FName> Keys;
	CutomKeyEvents.GenerateKeyArray(Keys);
	for (size_t i = 0; i < Keys.Num(); i++)
	{
		InputConfigureLibrary::GetOtherInputKeysFromKeyName(Keys[i], CutomKeyEvents.FindRef(Keys[i])->Keys);
	}
}



void UWGI_UserWidget::AddChildWGIUserWidget(UWGI_UserWidget*& Widget)
{
	OverrideUserWidget(Widget);
}

void UWGI_UserWidget::ChildWGIUserWidgetOnRemoved(UWGI_UserWidget* Widget)
{
	ChildWGIUserWidget.Remove(Widget);
}

FScriptDelegate UWGI_UserWidget::BindUFunctionToDelegate(const FName UFunctionName)
{
	FScriptDelegate FSD = FScriptDelegate();
	FSD.BindUFunction(this, UFunctionName);
	return FSD;
}

void UWGI_UserWidget::NativeConstruct()
{
	bIsFocusable = true;
	SetVisibility(ESlateVisibility::Visible);

	InputConfigureLibrary::BindOnConfigReloadEvent(this);

	if (bOverrideAllChildSetting)
	{
		UWidget* RootWidget = GetRootWidget();
		OverrideChildWidgetFocus(RootWidget);
	}

	Super::NativeConstruct();
}

void UWGI_UserWidget::NativeDestruct()
{


	InputConfigureLibrary::UnBindOnConfigReloadEvent(this);

	NavDataCache = nullptr;
	EnterKeyNav = nullptr;

	for (size_t i = 0; i < NavDatas.Num(); i++)
	{
		delete NavDatas[i];
	}
	NavDatas.Empty();

	TArray<FCustomKeyDelegateGroup*> Events;
	for (size_t i = 0; i < Events.Num(); i++)
	{
		delete Events[i];
	}
	CutomKeyEvents.Empty();


	DestructEvent.Broadcast(this);
	Super::NativeDestruct();
}

FReply UWGI_UserWidget::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
	InputConfigureLibrary::CallAnyKeyDownEvent(InKeyEvent, true);

	if (EnterKeyToNav(InKeyEvent))
	{
		return FReply::Handled();
	}
	if (EnterKeyDownToCutom(InGeometry, InKeyEvent))
	{
		return FReply::Handled();
	}
	if (InputConfigureLibrary::ThisIsEnterKey(InKeyEvent))
		if (EnterKeyNav != nullptr)
		{
			CallClickEvent(EnterKeyNav);
			return FReply::Handled();
		}
		else if (this->GetClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UWGI_UserWidget, EnterKeyEvent), EIncludeSuperFlag::ExcludeSuper) != nullptr)
		{
			EnterKeyEvent(InGeometry, true);
			return FReply::Handled();
		}

	if (InputConfigureLibrary::ThisIsBackKey(InKeyEvent))
		if (this->GetClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UWGI_UserWidget, BackKeyEvent), EIncludeSuperFlag::ExcludeSuper) != nullptr)
		{
			BackKeyEvent(InGeometry, true);
			return FReply::Handled();
		}
		else if (GetParent() == nullptr)
		{
			RemoveWidgetFromViewport(false);
			return FReply::Handled();
		}


	for (size_t i = 0; i < ChildWGIUserWidget.Num(); i++)
	{
		if (ChildWGIUserWidget[i]->IsVisible())
		{
			FReply Reply = ChildWGIUserWidget[i]->NativeOnKeyDown(InGeometry, InKeyEvent);

			if (Reply.IsEventHandled())
			{
				return Reply;
			}
		}
	}


	return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
}

FReply UWGI_UserWidget::NativeOnKeyUp(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
	InputConfigureLibrary::CallAnyKeyDownEvent(InKeyEvent, false);

	if (EnterKeyUpToCutom(InGeometry, InKeyEvent))
	{
		return FReply::Handled();
	}
	if (InputConfigureLibrary::ThisIsEnterKey(InKeyEvent))
		if (this->GetClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UWGI_UserWidget, EnterKeyEvent), EIncludeSuperFlag::ExcludeSuper) != nullptr)
		{
			EnterKeyEvent(InGeometry, false);
			return FReply::Handled();
		}

	if (InputConfigureLibrary::ThisIsBackKey(InKeyEvent))
		if (this->GetClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UWGI_UserWidget, BackKeyEvent), EIncludeSuperFlag::ExcludeSuper) != nullptr)
		{
			BackKeyEvent(InGeometry, false);
			return FReply::Handled();
		}



	for (size_t i = 0; i < ChildWGIUserWidget.Num(); i++)
	{
		FReply Reply = ChildWGIUserWidget[i]->NativeOnKeyUp(InGeometry, InKeyEvent);

		if (Reply.IsEventHandled())
		{
			return Reply;
		}
	}

	return Super::NativeOnKeyUp(InGeometry, InKeyEvent);
}

void UWGI_UserWidget::NativeOnFocusLost(const FFocusEvent& InFocusEvent)
{
	Super::NativeOnFocusLost(InFocusEvent);
	/*if (bForceLockOnWidgetFocus)
	{
		if (InFocusEvent.GetCause() == EFocusCause::Mouse)
		{
			ResetFocus();
		}
	}*/
}




void UWGI_UserWidget::ResetFocus()
{
	SetUserFocus(GetOwningPlayer());
	SetFocus();
}

void UWGI_UserWidget::OverrideChildWidgetFocus(UWidget* inParentWidget)
{
	if (IsValid(inParentWidget))
	{
		inParentWidget->SetAllNavigationRules(EUINavigationRule::Stop, NAME_None);
		if (OverridePanelWidget(inParentWidget)) { return; }
		if (SetSliderFocusable(inParentWidget)) { return; }
		if (SetComboBoxFocusable(inParentWidget)) { return; }
		if (SetInputKeySelector(inParentWidget)) { return; }
		if (OverrideUserWidget(inParentWidget)) { return; }

		inParentWidget->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
	}
}

bool UWGI_UserWidget::OverridePanelWidget(UWidget* inWidget)
{
	UPanelWidget* PanelWidget = Cast<UPanelWidget>(inWidget);
	if (PanelWidget)
	{
		int ChildCount = PanelWidget->GetChildrenCount();
		for (size_t i = 0; i < ChildCount; i++)
		{
			OverrideChildWidgetFocus(PanelWidget->GetChildAt(i));
		}

		if (SetButtonFocusable(PanelWidget)) { return true; }
		if (SetCheckBoxFocusable(PanelWidget)) { return true; }
		if (SetScrollBoxFocusable(PanelWidget)) { return true; }

		PanelWidget->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
		return true;
	}
	return false;
}

bool UWGI_UserWidget::SetButtonFocusable(UWidget* inWidget)
{
	UButton* Button = Cast<UButton>(inWidget);
	if (Button)
	{
		if (Cast<UWGI_Button>(Button))
		{
			Cast<UWGI_Button>(Button)->OnResetFocus.BindUObject(this, &UWGI_UserWidget::ResetFocus);
		}
		else
		{
			Button->IsFocusable = false;
			Button->OnClicked.Add(BindUFunctionToDelegate(TEXT("ResetFocus")));
		}
		return true;
	}
	return false;
}

bool UWGI_UserWidget::SetCheckBoxFocusable(UWidget* inWidget)
{
	UCheckBox* CheckBox = Cast<UCheckBox>(inWidget);
	if (CheckBox)
	{
		CheckBox->IsFocusable = false;
		return true;
	}
	return false;
}

bool UWGI_UserWidget::SetScrollBoxFocusable(UWidget* inWidget)
{
	UScrollBox* ScrollBox = Cast<UScrollBox>(inWidget);
	if (ScrollBox)
	{
		ScrollBox->SetVisibility(ESlateVisibility::Visible);
		return true;
	}
	return false;
}

bool UWGI_UserWidget::SetSliderFocusable(UWidget* inWidget)
{
	USlider* Slider = Cast<USlider>(inWidget);
	if (Slider)
	{
		Slider->IsFocusable = false;
		return true;
	}
	return false;
}

bool UWGI_UserWidget::SetComboBoxFocusable(UWidget* inWidget)
{
	UComboBox* ComboBox = Cast<UComboBox>(inWidget);
	if (ComboBox)
	{
		ComboBox->bIsFocusable = false;
		return true;
	}
	return false;
}

bool UWGI_UserWidget::SetInputKeySelector(UWidget* inWidget)
{
	if (Cast<UWGI_InputKeySelector>(inWidget))
	{
		Cast<UWGI_InputKeySelector>(inWidget)->OnResetFocus.BindUObject(this, &UWGI_UserWidget::ResetFocus);
		return true;
	}
	if (Cast<UInputKeySelector>(inWidget))
	{
		Cast<UInputKeySelector>(inWidget)->OnKeySelected.Add(BindUFunctionToDelegate(TEXT("ResetFocusFromInputKeySelector")));
		return true;
	}
	return false;
}

bool UWGI_UserWidget::OverrideUserWidget(UWidget* inWidget, bool bAddToChildWGI)
{
	if (bAddToChildWGI)
	{
		if (Cast<UWGI_UserWidget>(inWidget))
		{
			if (ChildWGIUserWidget.Contains(inWidget))
			{
				UE_LOG(WGI_UserWidgetLog, Warning, TEXT("Check for the same WGIWdiget in the WGIWdiget. --- %s"), *inWidget->GetName());
			}
			else
			{
				Cast<UWGI_UserWidget>(inWidget)->DestructEvent.Add(BindUFunctionToDelegate(TEXT("ChildWGIUserWidgetOnRemoved")));
				ChildWGIUserWidget.Add(Cast<UWGI_UserWidget>(inWidget));
			}

			inWidget->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
			return true;
		}
	}
	if (Cast<UWGI_NavItem>(inWidget))
	{
		Cast<UWGI_NavItem>(inWidget)->SetOwnerWGI(this);
	}
	UUserWidget* Widget = Cast<UUserWidget>(inWidget);
	if (Widget)
	{
		UWidget* RootWidget = Widget->GetRootWidget();
		OverrideChildWidgetFocus(RootWidget);
		Widget->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
		return true;
	}
	return false;
}




bool UWGI_UserWidget::EnterKeyToNav(const FKeyEvent& InKeyEvent)
{
	const FInputActionKeyMapping Mapping = FInputActionKeyMapping(NAME_None, InKeyEvent.GetKey(),
		InKeyEvent.IsShiftDown(), InKeyEvent.IsControlDown(), InKeyEvent.IsAltDown(), InKeyEvent.IsCommandDown());

	for (size_t i = 0; i < NavDatas.Num(); i++)
	{
		if (NavDatas[i]->bActive)
		{
			const EWGINavDirection NavDirection = NavDatas[i]->GetNavDirectionData()->FindNavDirection(Mapping);

			switch (NavDirection)
			{
			case Up:	EnterUpToNav(NavDatas[i]);	return true;
			case Down:	EnterDownToNav(NavDatas[i]);	return true;
			case Right:	EnterRightToNav(NavDatas[i]);	return true;
			case Left:	EnterLeftToNav(NavDatas[i]);	return true;
			default:
				break;
			}
		}
	}

	return false;
}

void UWGI_UserWidget::EnterUpToNav(WGINavPanelData*& NavData)
{
	switch (NavData->GetNavPanelType())
	{
	case SingleRow:	SelectLast_SingleRow(NavData);	break;
	case FourDirections: SelectUp_FourDirections(NavData);	break;
	default:
		break;
	}

}

void UWGI_UserWidget::EnterDownToNav(WGINavPanelData*& NavData)
{
	switch (NavData->GetNavPanelType())
	{
	case SingleRow:	SelectNext_SingleRow(NavData);	break;
	case FourDirections: SelectDown_FourDirections(NavData);	break;
	default:
		break;
	}
}

void UWGI_UserWidget::EnterRightToNav(WGINavPanelData*& NavData)
{
	switch (NavData->GetNavPanelType())
	{
	case SingleRow:	SelectNext_SingleRow(NavData);	break;
	case FourDirections: SelectRight_FourDirections(NavData);	break;
	default:
		break;
	}
}

void UWGI_UserWidget::EnterLeftToNav(WGINavPanelData*& NavData)
{
	switch (NavData->GetNavPanelType())
	{
	case SingleRow:	SelectLast_SingleRow(NavData);	break;
	case FourDirections: SelectLeft_FourDirections(NavData); break;
	default:
		break;
	}
}

int UWGI_UserWidget::SelectItemInPanel(int SelectIndex, UPanelWidget* Panel)
{
	if (SelectIndex >= 0 && SelectIndex < Panel->GetChildrenCount())
	{
		CallOnSelectEvent(Panel->GetChildAt(SelectIndex));

		return SelectIndex;
	}
	else
	{
		if (Panel->GetChildrenCount() == 0)
		{
			return 0;
		}

		UE_LOG(WGI_UserWidgetLog, Warning, TEXT("Unable to select Item , Beyond panel limits ! ---Index: %d , Panel: %s"), SelectIndex, *Panel->GetName());
		return SelectItemInPanel(0, Panel);
	}
}

int UWGI_UserWidget::SelectItemInPanel(int SelectIndex, UPanelWidget* Panel, FNavDelegate* Delegate)
{
	if (SelectIndex >= 0 && SelectIndex < Panel->GetChildrenCount())
	{
		CallOnSelectEvent(Panel->GetChildAt(SelectIndex), Delegate);

		return SelectIndex;
	}
	else
	{
		if (Panel->GetChildrenCount() == 0)
		{
			return 0;
		}

		UE_LOG(WGI_UserWidgetLog, Warning, TEXT("Unable to select Item , Beyond panel limits ! ---Index: %d , Panel: %s"), SelectIndex, *Panel->GetName());
		return SelectItemInPanel(0, Panel, Delegate);
	}
}

void UWGI_UserWidget::UnSelectItemInPanel(int UnSelectIndex, UPanelWidget* Panel)
{
	if (UnSelectIndex >= 0 && UnSelectIndex < Panel->GetChildrenCount())
	{
		CallOnUnSelectEvent(Panel->GetChildAt(UnSelectIndex));
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Warning, TEXT("Unable to UnSelect Item , Beyond panel limits ! ---Index: %d , Panel: %s"), UnSelectIndex, *Panel->GetName());
	}
}

void UWGI_UserWidget::UnSelectItemInPanel(int UnSelectIndex, UPanelWidget* Panel, FNavDelegate* Delegate)
{
	if (UnSelectIndex >= 0 && UnSelectIndex < Panel->GetChildrenCount())
	{
		CallOnUnSelectEvent(Panel->GetChildAt(UnSelectIndex), Delegate);
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Warning, TEXT("Unable to UnSelect Item , Beyond panel limits ! ---Index: %d , Panel: %s"), UnSelectIndex, *Panel->GetName());
	}
}

void UWGI_UserWidget::SelectLast_SingleRow(WGINavPanelData*& NavData)
{
	UPanelWidget* Panel = NavData->GetNavPanel();
	const int SelectedIndex = NavData->GetSelectedIndex();
	int NextIndex = SelectedIndex;

	if (SelectedIndex == 0)
	{
		if (NavData->GetIsLoop())
		{
			NextIndex = FMath::Clamp(Panel->GetChildrenCount() - 1, 0, Panel->GetChildrenCount() - 1);
		}
		else
		{
			return;
		}
	}
	else
	{
		NextIndex = SelectedIndex - 1;
	}

	if (NavData->GetSelectedIndex() != NextIndex)
	{
		UWidget* Child = Panel->GetChildAt(NextIndex);

		if (NavData->HasNavDelegate())
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex), NavData->GetNavDelegate());
			CallOnSelectEvent(Child, NavData->GetNavDelegate());
		}
		else
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex));
			CallOnSelectEvent(Child);
		}

		NavData->SetSelectedIndex(NextIndex);
	}
}

void UWGI_UserWidget::SelectNext_SingleRow(WGINavPanelData*& NavData)
{
	UPanelWidget* Panel = NavData->GetNavPanel();
	const int SelectedIndex = NavData->GetSelectedIndex();
	int NextIndex = SelectedIndex;

	if (SelectedIndex == Panel->GetChildrenCount() - 1)
	{
		if (NavData->GetIsLoop())
		{
			NextIndex = 0;
		}
		else
		{
			return;
		}
	}
	else
	{
		NextIndex = SelectedIndex + 1;
	}

	if (NavData->GetSelectedIndex() != NextIndex)
	{
		UWidget* Child = Panel->GetChildAt(NextIndex);

		if (NavData->HasNavDelegate())
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex), NavData->GetNavDelegate());
			CallOnSelectEvent(Child, NavData->GetNavDelegate());
		}
		else
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex));
			CallOnSelectEvent(Child);
		}

		NavData->SetSelectedIndex(NextIndex);
	}
}

void UWGI_UserWidget::SelectLeft_FourDirections(WGINavPanelData*& NavData)
{
	UPanelWidget* Panel = NavData->GetNavPanel();
	const int SelectedIndex = NavData->GetSelectedIndex();
	int NextIndex = 0;

	const int MaxColumn = NavData->GetColumn();
	int CRLastColumn = MaxColumn - 1;
	const int SelectedRow = SelectedIndex / MaxColumn;
	int SelectedColumn = SelectedIndex % MaxColumn;

	if (SelectedRow == (Panel->GetChildrenCount() - 1) / MaxColumn)
	{
		CRLastColumn = (Panel->GetChildrenCount() - 1) % MaxColumn;
	}

	if (SelectedColumn == 0)
	{
		if (NavData->GetIsLoop())
		{
			SelectedColumn = CRLastColumn;
		}
		else
		{
			return;
		}
	}
	else
	{
		SelectedColumn = SelectedColumn - 1;
	}

	NextIndex = SelectedRow * MaxColumn + SelectedColumn;

	if (NavData->GetSelectedIndex() != NextIndex)
	{
		UWidget* Child = Panel->GetChildAt(NextIndex);

		if (NavData->HasNavDelegate())
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex), NavData->GetNavDelegate());
			CallOnSelectEvent(Child, NavData->GetNavDelegate());
		}
		else
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex));
			CallOnSelectEvent(Child);
		}

		NavData->SetSelectedIndex(NextIndex);
	}
}

void UWGI_UserWidget::SelectRight_FourDirections(WGINavPanelData*& NavData)
{
	UPanelWidget* Panel = NavData->GetNavPanel();
	const int SelectedIndex = NavData->GetSelectedIndex();
	int NextIndex = 0;

	const int MaxColumn = NavData->GetColumn();
	int CRLastColumn = MaxColumn - 1;
	const int SelectedRow = SelectedIndex / MaxColumn;
	int SelectedColumn = SelectedIndex % MaxColumn;

	if (SelectedRow == (Panel->GetChildrenCount() - 1) / MaxColumn)
	{
		CRLastColumn = (Panel->GetChildrenCount() - 1) % MaxColumn;
	}

	if (SelectedColumn == CRLastColumn)
	{
		if (NavData->GetIsLoop())
		{
			SelectedColumn = 0;
		}
		else
		{
			return;
		}
	}
	else
	{
		SelectedColumn = SelectedColumn + 1;
	}

	NextIndex = SelectedRow * MaxColumn + SelectedColumn;

	if (NavData->GetSelectedIndex() != NextIndex)
	{
		UWidget* Child = Panel->GetChildAt(NextIndex);

		if (NavData->HasNavDelegate())
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex), NavData->GetNavDelegate());
			CallOnSelectEvent(Child, NavData->GetNavDelegate());
		}
		else
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex));
			CallOnSelectEvent(Child);
		}

		NavData->SetSelectedIndex(NextIndex);
	}
}

void UWGI_UserWidget::SelectUp_FourDirections(WGINavPanelData*& NavData)
{
	UPanelWidget* Panel = NavData->GetNavPanel();
	const int SelectedIndex = NavData->GetSelectedIndex();
	int NextIndex = 0;

	const int MaxColumn = NavData->GetColumn();
	const int RowCount = (Panel->GetChildrenCount() - 1) / MaxColumn;
	int SelectedRow = SelectedIndex / MaxColumn;
	int SelectedColumn = SelectedIndex % MaxColumn;

	if (SelectedRow == 0)
	{
		if (NavData->GetIsLoop())
		{
			SelectedRow = RowCount;

			int CRLastColumn = (Panel->GetChildrenCount() - 1) % MaxColumn;

			if (SelectedColumn > CRLastColumn)
			{
				SelectedRow = FMath::Clamp(SelectedRow - 1, 0, RowCount);
			}
		}
		else
		{
			return;
		}
	}
	else
	{
		SelectedRow = SelectedRow - 1;
	}

	NextIndex = SelectedRow * MaxColumn + SelectedColumn;

	if (NavData->GetSelectedIndex() != NextIndex)
	{
		UWidget* Child = Panel->GetChildAt(NextIndex);

		if (NavData->HasNavDelegate())
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex), NavData->GetNavDelegate());
			CallOnSelectEvent(Child, NavData->GetNavDelegate());
		}
		else
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex));
			CallOnSelectEvent(Child);
		}

		NavData->SetSelectedIndex(NextIndex);
	}
}

void UWGI_UserWidget::SelectDown_FourDirections(WGINavPanelData*& NavData)
{
	UPanelWidget* Panel = NavData->GetNavPanel();
	const int SelectedIndex = NavData->GetSelectedIndex();
	int NextIndex = 0;

	const int MaxColumn = NavData->GetColumn();
	const int RowCount = (Panel->GetChildrenCount() - 1) / MaxColumn;
	int SelectedRow = SelectedIndex / MaxColumn;
	int SelectedColumn = SelectedIndex % MaxColumn;

	if (RowCount == SelectedRow)
	{
		if (NavData->GetIsLoop())
		{
			SelectedRow = 0;
		}
		else
		{
			return;
		}
	}
	else
	{
		SelectedRow = SelectedRow + 1;

		int CRLastColumn = MaxColumn - 1;
		if (SelectedRow == RowCount)
		{
			CRLastColumn = (Panel->GetChildrenCount() - 1) % MaxColumn;
		}
		if (SelectedColumn > CRLastColumn)
		{
			if (NavData->GetIsLoop())
			{
				SelectedRow = 0;
			}
			else
			{
				return;
			}
		}
	}

	NextIndex = SelectedRow * MaxColumn + SelectedColumn;

	if (NavData->GetSelectedIndex() != NextIndex)
	{
		UWidget* Child = Panel->GetChildAt(NextIndex);

		if (NavData->HasNavDelegate())
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex), NavData->GetNavDelegate());
			CallOnSelectEvent(Child, NavData->GetNavDelegate());
		}
		else
		{
			CallOnUnSelectEvent(Panel->GetChildAt(SelectedIndex));
			CallOnSelectEvent(Child);
		}

		NavData->SetSelectedIndex(NextIndex);
	}
}

void UWGI_UserWidget::CallOnSelectEvent(UWidget* Child)
{
	if (Cast<UWGI_NavItem>(Child))
	{
		Cast<UWGI_NavItem>(Child)->OnSelectEvent();

	}
	else if (Child->GetClass()->ImplementsInterface(UWGI_NavInterface::StaticClass()))
	{
		IWGI_NavInterface::Execute_OnSelectInterface(Child);
	}
	else
	{
		UE_LOG(WGI_NavInterface, Warning, TEXT("This Widget does not inherit from the navigation event interface --- %s"), *Child->GetName());
	}

}

void UWGI_UserWidget::CallOnSelectEvent(UWidget* Child, FNavDelegate* Delegate)
{
	Delegate->Delegate_SelectedEvent.ExecuteIfBound(Child);
}

void UWGI_UserWidget::CallOnUnSelectEvent(UWidget* Child)
{
	if (Cast<UWGI_NavItem>(Child))
	{
		Cast<UWGI_NavItem>(Child)->OnUnSelectEvent();
	}
	else if (Child->GetClass()->ImplementsInterface(UWGI_NavInterface::StaticClass()))
	{
		IWGI_NavInterface::Execute_OnUnSelectInterface(Child);
	}
	else
	{
		UE_LOG(WGI_NavInterface, Warning, TEXT("This Widget does not inherit from the navigation event interface --- %s"), *Child->GetName());
	}
}

void UWGI_UserWidget::CallOnUnSelectEvent(UWidget* Child, FNavDelegate* Delegate)
{
	Delegate->Delegate_UnSelectedEvent.ExecuteIfBound(Child);
}

void UWGI_UserWidget::CallClickEvent(WGINavPanelData*& NavData)
{
	UWidget* Widget = NavData->GetNavPanel()->GetChildAt(NavData->GetSelectedIndex());

	if (NavData->HasNavDelegate())
	{
		NavData->GetNavDelegate()->Delegate_ClickedEvent.ExecuteIfBound(Widget);
	}
	else
	{
		if (Cast<UWGI_NavItem>(Widget))
		{
			Cast<UWGI_NavItem>(Widget)->OnClickEvent();
		}
		else if (Widget->GetClass()->ImplementsInterface(UWGI_NavInterface::StaticClass()))
		{
			IWGI_NavInterface::Execute_OnClickInterface(Widget);
		}
		else
		{
			UE_LOG(WGI_NavInterface, Warning, TEXT("This Widget does not inherit from the navigation event interface --- %s"), *Widget->GetName());
		}
	}
}







void UWGI_UserWidget::AddNavFroHorizontalBox(UHorizontalBox*& HorizontalBox, FName LeftKey, FName RightKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(HorizontalBox, EWGINavPanelType::SingleRow, bIsLoop, InitSelectedIndex);

	Data->GetNavDirectionData()->LeftKeyName = LeftKey;
	Data->GetNavDirectionData()->RightKeyName = RightKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(LeftKey, Data->GetNavDirectionData()->LeftDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(RightKey, Data->GetNavDirectionData()->RightDirectionKeys);
	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, HorizontalBox));
}

void UWGI_UserWidget::AddNavFroHorizontalBox_Delegate(UHorizontalBox*& HorizontalBox, FOnNavClickedEvent OnClickedEvent, FOnNavSelectedEvent OnSelectedEvent, FOnNavUnSelectedEvent OnUnSelectedEvent,
	FName LeftKey, FName RightKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(HorizontalBox, EWGINavPanelType::SingleRow, bIsLoop, InitSelectedIndex);

	Data->GetNavDirectionData()->LeftKeyName = LeftKey;
	Data->GetNavDirectionData()->RightKeyName = RightKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(LeftKey, Data->GetNavDirectionData()->LeftDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(RightKey, Data->GetNavDirectionData()->RightDirectionKeys);

	Data->EnsureNavDelegateValid();
	Data->GetNavDelegate()->Delegate_ClickedEvent = OnClickedEvent;
	Data->GetNavDelegate()->Delegate_SelectedEvent = OnSelectedEvent;
	Data->GetNavDelegate()->Delegate_UnSelectedEvent = OnUnSelectedEvent;

	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, HorizontalBox, Data->GetNavDelegate()));
}

void UWGI_UserWidget::AddNavFroVerticalBox(UVerticalBox*& VerticalBox, FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(VerticalBox, EWGINavPanelType::SingleRow, bIsLoop, InitSelectedIndex);

	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);
	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, VerticalBox));
}

void UWGI_UserWidget::AddNavFroVerticalBox_Delegate(UVerticalBox*& VerticalBox, FOnNavClickedEvent OnClickedEvent, FOnNavSelectedEvent OnSelectedEvent, FOnNavUnSelectedEvent OnUnSelectedEvent,
	FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(VerticalBox, EWGINavPanelType::SingleRow, bIsLoop, InitSelectedIndex);

	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);

	Data->EnsureNavDelegateValid();
	Data->GetNavDelegate()->Delegate_ClickedEvent = OnClickedEvent;
	Data->GetNavDelegate()->Delegate_SelectedEvent = OnSelectedEvent;
	Data->GetNavDelegate()->Delegate_UnSelectedEvent = OnUnSelectedEvent;

	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, VerticalBox, Data->GetNavDelegate()));
}

void UWGI_UserWidget::AddNavFroScrollBox(UScrollBox*& ScrollBox, FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(ScrollBox, EWGINavPanelType::SingleRow, bIsLoop, InitSelectedIndex);

	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);
	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, ScrollBox));
}

void UWGI_UserWidget::AddNavFroScrollBox_Delegate(UScrollBox*& ScrollBox, FOnNavClickedEvent OnClickedEvent, FOnNavSelectedEvent OnSelectedEvent, FOnNavUnSelectedEvent OnUnSelectedEvent,
	FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(ScrollBox, EWGINavPanelType::SingleRow, bIsLoop, InitSelectedIndex);

	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);

	Data->EnsureNavDelegateValid();
	Data->GetNavDelegate()->Delegate_ClickedEvent = OnClickedEvent;
	Data->GetNavDelegate()->Delegate_SelectedEvent = OnSelectedEvent;
	Data->GetNavDelegate()->Delegate_UnSelectedEvent = OnUnSelectedEvent;

	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, ScrollBox, Data->GetNavDelegate()));
}

void UWGI_UserWidget::AddNavFroGridPanel(UGridPanel*& GridPanel, int MaxColumn, FName LeftKey, FName RightKey, FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(GridPanel, EWGINavPanelType::FourDirections, bIsLoop, InitSelectedIndex);

	Data->SetColumn(MaxColumn);
	Data->GetNavDirectionData()->LeftKeyName = LeftKey;
	Data->GetNavDirectionData()->RightKeyName = RightKey;
	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(LeftKey, Data->GetNavDirectionData()->LeftDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(RightKey, Data->GetNavDirectionData()->RightDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);
	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, GridPanel));
}

void UWGI_UserWidget::AddNavFroGridPanel_Delegate(UGridPanel*& GridPanel, int MaxColumn, FOnNavClickedEvent OnClickedEvent, FOnNavSelectedEvent OnSelectedEvent, FOnNavUnSelectedEvent OnUnSelectedEvent,
	FName LeftKey, FName RightKey, FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(GridPanel, EWGINavPanelType::FourDirections, bIsLoop, InitSelectedIndex);

	Data->SetColumn(MaxColumn);
	Data->GetNavDirectionData()->LeftKeyName = LeftKey;
	Data->GetNavDirectionData()->RightKeyName = RightKey;
	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(LeftKey, Data->GetNavDirectionData()->LeftDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(RightKey, Data->GetNavDirectionData()->RightDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);

	Data->EnsureNavDelegateValid();
	Data->GetNavDelegate()->Delegate_ClickedEvent = OnClickedEvent;
	Data->GetNavDelegate()->Delegate_SelectedEvent = OnSelectedEvent;
	Data->GetNavDelegate()->Delegate_UnSelectedEvent = OnUnSelectedEvent;

	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, GridPanel, Data->GetNavDelegate()));
}

void UWGI_UserWidget::AddNavFroUniformGridPanel(UUniformGridPanel*& UniformGridPanel, int MaxColumn, FName LeftKey, FName RightKey, FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(UniformGridPanel, EWGINavPanelType::FourDirections, bIsLoop, InitSelectedIndex);

	Data->SetColumn(MaxColumn);
	Data->GetNavDirectionData()->LeftKeyName = LeftKey;
	Data->GetNavDirectionData()->RightKeyName = RightKey;
	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(LeftKey, Data->GetNavDirectionData()->LeftDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(RightKey, Data->GetNavDirectionData()->RightDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);
	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, UniformGridPanel));
}

void UWGI_UserWidget::AddNavFroUniformGridPanel_Delegate(UUniformGridPanel*& UniformGridPanel, int MaxColumn, FOnNavClickedEvent OnClickedEvent, FOnNavSelectedEvent OnSelectedEvent, FOnNavUnSelectedEvent OnUnSelectedEvent,
	FName LeftKey, FName RightKey, FName UpKey, FName DownKey, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = Ex_AddNavFroPanel(UniformGridPanel, EWGINavPanelType::FourDirections, bIsLoop, InitSelectedIndex);

	Data->SetColumn(MaxColumn);
	Data->GetNavDirectionData()->LeftKeyName = LeftKey;
	Data->GetNavDirectionData()->RightKeyName = RightKey;
	Data->GetNavDirectionData()->UpKeyName = UpKey;
	Data->GetNavDirectionData()->DownKeyName = DownKey;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(LeftKey, Data->GetNavDirectionData()->LeftDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(RightKey, Data->GetNavDirectionData()->RightDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(UpKey, Data->GetNavDirectionData()->UpDirectionKeys);
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(DownKey, Data->GetNavDirectionData()->DownDirectionKeys);

	Data->EnsureNavDelegateValid();
	Data->GetNavDelegate()->Delegate_ClickedEvent = OnClickedEvent;
	Data->GetNavDelegate()->Delegate_SelectedEvent = OnSelectedEvent;
	Data->GetNavDelegate()->Delegate_UnSelectedEvent = OnUnSelectedEvent;

	Data->SetSelectedIndex(SelectItemInPanel(InitSelectedIndex, UniformGridPanel, Data->GetNavDelegate()));
}




void UWGI_UserWidget::ActiveThisNav(UPanelWidget*& PanelWidget)
{
	WGINavPanelData* Data = nullptr;
	if (GetExistingByPanelData(PanelWidget, Data))
	{
		Data->bActive = true;
	};
}
void UWGI_UserWidget::UnActiveThisNav(UPanelWidget*& PanelWidget)
{
	WGINavPanelData* Data = nullptr;
	if (GetExistingByPanelData(PanelWidget, Data))
	{
		Data->bActive = false;
	};
}
void UWGI_UserWidget::RemoveThisNav(UPanelWidget*& PanelWidget)
{
	for (size_t i = 0; i < NavDatas.Num(); i++)
	{
		if (*NavDatas[i] == PanelWidget)
		{
			if (NavDatas[i] == NavDataCache)
			{
				NavDataCache = nullptr;
			}

			delete NavDatas[i];
			NavDatas.RemoveAt(i);
			return;
		}
	}
}




UPanelSlot* UWGI_UserWidget::AddChildToNavPanel(UPanelWidget*& Panel, UWidget* Content, bool bSelectThis)
{
	int LastChildCount = Panel->GetChildrenCount();
	UPanelSlot* ResultSlot = Panel->AddChild(Content);
	OverrideUserWidget(Content, false);

	if (LastChildCount == 0)
	{
		WGINavPanelData* NavData = nullptr;
		if (GetExistingByPanelData(Panel, NavData))
		{
			NavData->SetSelectedIndex(0);
			if (NavData->HasNavDelegate())
			{
				CallOnSelectEvent(Content, NavData->GetNavDelegate());
			}
			else
			{
				CallOnSelectEvent(Content);
			}
		}
		else
		{
			UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- AddChildToNavPanel() --- %s"), *Panel->GetName());
		}
	}
	else if (bSelectThis)
	{
		WGINavPanelData* NavData = nullptr;
		if (GetExistingByPanelData(Panel, NavData))
		{
			if (NavData->HasNavDelegate())
			{
				CallOnUnSelectEvent(Panel->GetChildAt(NavData->GetSelectedIndex()), NavData->GetNavDelegate());
				CallOnSelectEvent(Content, NavData->GetNavDelegate());
			}
			else
			{
				CallOnUnSelectEvent(Panel->GetChildAt(NavData->GetSelectedIndex()));
				CallOnSelectEvent(Content);
			}
			NavData->SetSelectedIndex(LastChildCount);
		}
		else
		{
			UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- AddChildToNavPanel() --- %s"), *Panel->GetName());
		}
	}

	//if (Cast<UWGI_NavItem>(Content))
	//{
	//	Cast<UWGI_NavItem>(Content)->SetOwnerWGI(this);
	//}

	return ResultSlot;
}

UPanelSlot* UWGI_UserWidget::AddChildToNavPanel_GridPanel(UPanelWidget*& Panel, UWidget* Content, bool bSelectThis)
{
	int LastChildCount = Panel->GetChildrenCount();

	UPanelSlot* ResultSlot = Panel->AddChild(Content);
	OverrideUserWidget(Content, false);

	if (LastChildCount == 0)
	{
		WGINavPanelData* NavData = nullptr;
		if (GetExistingByPanelData(Panel, NavData))
		{
			NavData->SetSelectedIndex(0);
			if (NavData->HasNavDelegate())
			{
				CallOnSelectEvent(Content, NavData->GetNavDelegate());
			}
			else
			{
				CallOnSelectEvent(Content);
			}
		}
		else
		{
			UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- AddChildToNavPanel_GridPanel() --- %s"), *Panel->GetName());
		}
	}
	else if (bSelectThis)
	{
		WGINavPanelData* NavData = nullptr;
		if (GetExistingByPanelData(Panel, NavData))
		{
			if (NavData->HasNavDelegate())
			{
				CallOnUnSelectEvent(Panel->GetChildAt(NavData->GetSelectedIndex()), NavData->GetNavDelegate());
				CallOnSelectEvent(Content, NavData->GetNavDelegate());
			}
			else
			{
				CallOnUnSelectEvent(Panel->GetChildAt(NavData->GetSelectedIndex()));
				CallOnSelectEvent(Content);
			}
			NavData->SetSelectedIndex(LastChildCount);

			UGridSlot* GSlot = Cast<UGridSlot>(ResultSlot);
			if (GSlot)
			{
				GSlot->SetColumn((Panel->GetChildrenCount() - 1) % NavData->GetColumn());
				GSlot->SetRow((Panel->GetChildrenCount() - 1) / NavData->GetColumn());
			}
		}
		else
		{
			UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- AddChildToNavPanel_GridPanel() --- %s"), *Panel->GetName());
		}
	}

	//if (Cast<UWGI_NavItem>(Content))
	//{
	//	Cast<UWGI_NavItem>(Content)->SetOwnerWGI(this);
	//}

	return ResultSlot;
}

void UWGI_UserWidget::RemoveChildFromNavPanel(UPanelWidget*& Panel, UWidget* Content)
{
	int RemovedIndex = Panel->GetChildIndex(Content);

	if (Panel->RemoveChildAt(RemovedIndex))
	{
		WGINavPanelData* NavData = nullptr;
		if (GetExistingByPanelData(Panel, NavData))
		{
			int SelectedIndex = NavData->GetSelectedIndex();
			if (SelectedIndex > RemovedIndex)
			{
				NavData->SetSelectedIndex(SelectedIndex - 1);
			}
			else if (SelectedIndex == RemovedIndex)
			{
				SelectedIndex = FMath::Clamp(SelectedIndex - 1, 0, SelectedIndex);
				NavData->SetSelectedIndex(SelectedIndex);

				if (NavData->HasNavDelegate())
				{
					SelectItemInPanel(SelectedIndex, Panel, NavData->GetNavDelegate());
				}
				else
				{
					SelectItemInPanel(SelectedIndex, Panel);
				}
			}
		}
		else
		{
			UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- RemoveChildFromNavPanel() --- %s"), *Panel->GetName());
		}
	}
}

void UWGI_UserWidget::RemoveChildFromNavPanel_GridPanel(UPanelWidget*& Panel, UWidget* Content)
{
	int RemovedIndex = Panel->GetChildIndex(Content);
	if (Panel->RemoveChildAt(RemovedIndex))
	{
		WGINavPanelData* NavData = nullptr;
		if (GetExistingByPanelData(Panel, NavData))
		{
			for (size_t i = RemovedIndex; i < Panel->GetChildrenCount(); i++)
			{
				UGridSlot* GSlot = Cast<UGridSlot>(Panel->GetChildAt(i)->Slot);
				if (GSlot)
				{
					GSlot->SetColumn(i % NavData->GetColumn());
					GSlot->SetRow(i / NavData->GetColumn());
				}
			}

			int SelectedIndex = NavData->GetSelectedIndex();
			if (SelectedIndex > RemovedIndex)
			{
				NavData->SetSelectedIndex(SelectedIndex - 1);
			}
			else if (SelectedIndex == RemovedIndex)
			{
				SelectedIndex = FMath::Clamp(SelectedIndex, 0, Panel->GetChildrenCount() - 1);
				NavData->SetSelectedIndex(SelectedIndex);

				if (NavData->HasNavDelegate())
				{
					SelectItemInPanel(SelectedIndex, Panel, NavData->GetNavDelegate());
				}
				else
				{
					SelectItemInPanel(SelectedIndex, Panel);
				}
			}
		}
		else
		{
			UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- RemoveChildFromNavPanel_GridPanel() --- %s"), *Panel->GetName());
		}
	}
}

void UWGI_UserWidget::RemoveSelectedFromNavPanel(UPanelWidget*& Panel)
{
	WGINavPanelData* NavData = nullptr;
	if (GetExistingByPanelData(Panel, NavData))
	{
		int SelectedIndex = NavData->GetSelectedIndex();

		Panel->RemoveChildAt(SelectedIndex);

		SelectedIndex = FMath::Clamp(SelectedIndex - 1, 0, SelectedIndex);
		NavData->SetSelectedIndex(SelectedIndex);

		if (NavData->HasNavDelegate())
		{
			SelectItemInPanel(SelectedIndex, Panel, NavData->GetNavDelegate());
		}
		else
		{
			SelectItemInPanel(SelectedIndex, Panel);
		}
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- RemoveSelectedFromNavPanel() --- %s"), *Panel->GetName());
	}
}

void UWGI_UserWidget::RemoveSelectedFromNavPanel_GridPanel(UPanelWidget*& Panel)
{

	WGINavPanelData* NavData = nullptr;
	if (GetExistingByPanelData(Panel, NavData))
	{
		int SelectedIndex = NavData->GetSelectedIndex();

		Panel->RemoveChildAt(SelectedIndex);

		for (size_t i = SelectedIndex; i < Panel->GetChildrenCount(); i++)
		{
			UGridSlot* GSlot = Cast<UGridSlot>(Panel->GetChildAt(i)->Slot);
			if (GSlot)
			{
				GSlot->SetColumn(i % NavData->GetColumn());
				GSlot->SetRow(i / NavData->GetColumn());
			}
		}

		SelectedIndex = FMath::Clamp(SelectedIndex, 0, Panel->GetChildrenCount() - 1);
		NavData->SetSelectedIndex(SelectedIndex);

		if (NavData->HasNavDelegate())
		{
			SelectItemInPanel(SelectedIndex, Panel, NavData->GetNavDelegate());
		}
		else
		{
			SelectItemInPanel(SelectedIndex, Panel);
		}
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- RemoveSelectedFromNavPanel_GridPanel() --- %s"), *Panel->GetName());
	}
}

void UWGI_UserWidget::ClearChildrenOfNavPanel(UPanelWidget*& Panel)
{
	Panel->ClearChildren();
	WGINavPanelData* NavData = nullptr;
	if (GetExistingByPanelData(Panel, NavData))
	{
		NavData->SetSelectedIndex(0);
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- ClearChildrenOfNavPanel() --- %s"), *Panel->GetName());
	}
}

void UWGI_UserWidget::SelectItemAtNavPanel(UPanelWidget*& Panel, int SelectIndex, bool bCallEventWhenSelected, bool bJoinTheCache)
{
	if (NavDataCache)
		if (*NavDataCache == Panel)
		{
			int SelectedIndex = NavDataCache->GetSelectedIndex();

			if (SelectedIndex == SelectIndex)
			{
				if (bCallEventWhenSelected)
				{
					if (NavDataCache->HasNavDelegate())
					{
						SelectItemInPanel(SelectIndex, Panel, NavDataCache->GetNavDelegate());
					}
					else
					{
						SelectItemInPanel(SelectIndex, Panel);
					}
				}
			}
			else
			{
				if (NavDataCache->HasNavDelegate())
				{
					SelectItemInPanel(SelectIndex, Panel, NavDataCache->GetNavDelegate());
					UnSelectItemInPanel(SelectedIndex, Panel, NavDataCache->GetNavDelegate());
				}
				else
				{
					SelectItemInPanel(SelectIndex, Panel);
					UnSelectItemInPanel(SelectedIndex, Panel);
				}
			}

			NavDataCache->SetSelectedIndex(SelectIndex);
			if (!bJoinTheCache)
			{
				NavDataCache = nullptr;
			}

			return;
		}

	WGINavPanelData* NavData = nullptr;
	if (GetExistingByPanelData(Panel, NavData))
	{
		int SelectedIndex = NavData->GetSelectedIndex();

		if (SelectedIndex == SelectIndex)
		{
			if (bCallEventWhenSelected)
			{
				if (NavData->HasNavDelegate())
				{
					SelectItemInPanel(SelectIndex, Panel, NavData->GetNavDelegate());
				}
				else
				{
					SelectItemInPanel(SelectIndex, Panel);
				}
			}
		}
		else
		{
			if (NavData->HasNavDelegate())
			{
				SelectItemInPanel(SelectIndex, Panel, NavData->GetNavDelegate());
				UnSelectItemInPanel(SelectedIndex, Panel, NavData->GetNavDelegate());
			}
			else
			{
				SelectItemInPanel(SelectIndex, Panel);
				UnSelectItemInPanel(SelectedIndex, Panel);
			}
		}

		NavData->SetSelectedIndex(SelectIndex);
		if (bJoinTheCache)
		{
			NavDataCache = nullptr;
			NavDataCache = NavData;
		}
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- SelectItemAtNavPanel() --- %s"), *Panel->GetName());
	}
}


UWidget* UWGI_UserWidget::GetSelectedItemFromNavPanel(UPanelWidget*& Panel)
{
	WGINavPanelData* NavData = nullptr;
	if (GetExistingByPanelData(Panel, NavData))
	{
		return NavData->GetNavPanel()->GetChildAt(NavData->GetSelectedIndex());
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- GetSelectedItemFromNavPanel() --- %s"), *Panel->GetName());
	}

	return nullptr;
}

int UWGI_UserWidget::GetSelectedIndexFromNavPanel(UPanelWidget*& Panel)
{
	WGINavPanelData* NavData = nullptr;
	if (GetExistingByPanelData(Panel, NavData))
	{
		return NavData->GetSelectedIndex();
	}
	else
	{
		UE_LOG(WGI_UserWidgetLog, Error, TEXT(" Not Find This Nav Panel --- GetSelectedIndexFromNavPanel() --- %s"), *Panel->GetName());
	}

	return 0;
}

bool UWGI_UserWidget::GetExistingByPanelData(UPanelWidget* Panel, WGINavPanelData*& OutData)
{
	for (size_t i = 0; i < NavDatas.Num(); i++)
	{
		if (*NavDatas[i] == Panel)
		{
			OutData = NavDatas[i];
			return true;
		}
	}
	return false;
}

WGINavPanelData* UWGI_UserWidget::Ex_AddNavFroPanel(UPanelWidget* Panel, EWGINavPanelType PanelType, bool bIsLoop, int InitSelectedIndex)
{
	WGINavPanelData* Data = nullptr;
	if (GetExistingByPanelData(Panel, Data))
	{
		Data->GetNavDirectionData()->Clear();
		Data->EnsureClearNavDelegate();
		Data->SetSelectedIndex(InitSelectedIndex);
		Data->SetIsLoop(bIsLoop);
		Data->bActive = true;
		UE_LOG(WGI_UserWidgetLog, Log, TEXT("Override Nav . %s"), *Panel->GetName());
	}
	else
	{
		Data = new WGINavPanelData(Panel, PanelType, bIsLoop, InitSelectedIndex);
		NavDatas.Add(Data);
	}
	return Data;
}




void UWGI_UserWidget::ActiveThisKey(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bDownActive = true;
		CutomKeyEvents.FindRef(KeyName)->bUpActive = true;
	}
}
void UWGI_UserWidget::ActiveThisKeyDown(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bDownActive = true;
	}
}
void UWGI_UserWidget::ActiveThisKeyUp(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bUpActive = true;
	}
}
void UWGI_UserWidget::UnActiveThisKey(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bDownActive = false;
		CutomKeyEvents.FindRef(KeyName)->bUpActive = false;
	}
}
void UWGI_UserWidget::UnActiveThisKeyDown(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bDownActive = false;
	}
}
void UWGI_UserWidget::UnActiveThisKeyUp(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bUpActive = false;
	}
}
void UWGI_UserWidget::RemoveThisKey(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		delete CutomKeyEvents.FindRef(KeyName);
		CutomKeyEvents.Remove(KeyName);
	}
}
void UWGI_UserWidget::RemoveThisKeyDown(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->ClearDownEvent();
	}
}
void UWGI_UserWidget::RemoveThisKeyUp(FName KeyName)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->ClearUpEvent();
	}
}



void UWGI_UserWidget::BindEnterKeyToNav(UPanelWidget*& NavPanel)
{
	EnterKeyNav = nullptr;
	GetExistingByPanelData(NavPanel, EnterKeyNav);
}

void UWGI_UserWidget::UnBindEnterKey()
{
	EnterKeyNav = nullptr;
}


void UWGI_UserWidget::AddKeyEvent(FName KeyName, FOnKeyDownEvent OnKeyDownEvent, FOnKeyUpEvent OnKeyUpEvent)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bDownActive = true;
		CutomKeyEvents.FindRef(KeyName)->BindDownEvent(OnKeyDownEvent);
		CutomKeyEvents.FindRef(KeyName)->bUpActive = true;
		CutomKeyEvents.FindRef(KeyName)->BindUpEvent(OnKeyUpEvent);
	}

	TArray<FInputActionKeyMapping>* Keys = nullptr;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(KeyName, Keys);

	FCustomKeyDelegateGroup* KeyEvent = new FCustomKeyDelegateGroup(Keys);
	KeyEvent->BindDownEvent(OnKeyDownEvent);
	KeyEvent->BindUpEvent(OnKeyUpEvent);

	CutomKeyEvents.Add(KeyName, KeyEvent);
}

void UWGI_UserWidget::AddKeyDownEvent(FName KeyName, FOnKeyDownEvent OnKeyDownEvent)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bDownActive = true;
		CutomKeyEvents.FindRef(KeyName)->BindDownEvent(OnKeyDownEvent);
	}

	TArray<FInputActionKeyMapping>* Keys = nullptr;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(KeyName, Keys);

	FCustomKeyDelegateGroup* KeyEvent = new FCustomKeyDelegateGroup(Keys);
	KeyEvent->BindDownEvent(OnKeyDownEvent);

	CutomKeyEvents.Add(KeyName, KeyEvent);
}

void UWGI_UserWidget::AddKeyUpEvent(FName KeyName, FOnKeyUpEvent OnKeyUpEvent)
{
	if (CutomKeyEvents.Contains(KeyName))
	{
		CutomKeyEvents.FindRef(KeyName)->bUpActive = true;
		CutomKeyEvents.FindRef(KeyName)->BindUpEvent(OnKeyUpEvent);
	}

	TArray<FInputActionKeyMapping>* Keys = nullptr;
	InputConfigureLibrary::GetOtherInputKeysFromKeyName(KeyName, Keys);

	FCustomKeyDelegateGroup* KeyEvent = new FCustomKeyDelegateGroup(Keys);
	KeyEvent->BindUpEvent(OnKeyUpEvent);

	CutomKeyEvents.Add(KeyName, KeyEvent);
}

bool UWGI_UserWidget::EnterKeyDownToCutom(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
	TArray<FCustomKeyDelegateGroup*> Keys;
	CutomKeyEvents.GenerateValueArray(Keys);
	for (size_t i = 0; i < Keys.Num(); i++)
	{
		FCustomKeyDelegateGroup*& DeG = Keys[i];
		if (DeG->bDownActive)
		{
			if (DeG->HasThisKey(FInputActionKeyMapping(NAME_None, InKeyEvent.GetKey(), InKeyEvent.IsShiftDown(), InKeyEvent.IsControlDown(), InKeyEvent.IsAltDown(), InKeyEvent.IsCommandDown())))
			{
				if (DeG->HasBindDownEvent())
				{
					DeG->GetDownEvent()->ExecuteIfBound(InGeometry, InKeyEvent);
					return true;
				}
			}
		}
	}
	return false;
}

bool UWGI_UserWidget::EnterKeyUpToCutom(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
	TArray<FCustomKeyDelegateGroup*> Keys;
	CutomKeyEvents.GenerateValueArray(Keys);
	for (size_t i = 0; i < Keys.Num(); i++)
	{
		FCustomKeyDelegateGroup*& DeG = Keys[i];
		if (DeG->bUpActive)
		{
			if (DeG->HasThisKey(FInputActionKeyMapping(NAME_None, InKeyEvent.GetKey(), InKeyEvent.IsShiftDown(), InKeyEvent.IsControlDown(), InKeyEvent.IsAltDown(), InKeyEvent.IsCommandDown())))
			{
				if (DeG->HasBindUpEvent())
				{
					DeG->GetUpEvent()->ExecuteIfBound(InGeometry, InKeyEvent);
					return true;
				}
			}
		}
	}
	return false;
}

